/*
 * Cinta.h
 *
 *  Created on: Nov 19, 2013
 *      Author: m
 */

#ifndef CINTA_H_
#define CINTA_H_

#include "ElementoProduccion.h"

/*
 * Cinta Genérica
 */
template < int CANTIDAD_SLOTS >
class Cinta
{
protected:
    class SlotCinta
    {
    protected:
        bool m_estaVacio;
        ElementoProduccion m_elemento;

    public:
        SlotCinta() :
            m_estaVacio(true),
            m_elemento()
        {
        }

        ~SlotCinta()
        {
        }

        bool estaVacio()
        {
            return m_estaVacio;
        }

        void depositarElemento( const ElementoProduccion &e )
        {
            m_elemento = e;

            m_estaVacio = false;
        }

        ElementoProduccion* obtenerElemento()
        {
            return &m_elemento;
        }

        ElementoProduccion quitarElemento()
        {
            m_estaVacio = true;

            return m_elemento;
        }
    };

protected:
    SlotCinta m_slots[CANTIDAD_SLOTS];

    int m_primerPosicion;

    SlotCinta* getPrimerSlot()
    {
        return &m_slots[ m_primerPosicion ];
    }

    SlotCinta* getUltimoSlot()
    {
        return &m_slots[ ( m_primerPosicion + CANTIDAD_SLOTS - 1 ) % CANTIDAD_SLOTS ];
    }

public:
    Cinta() :
        m_primerPosicion( 0 )
    {
    }

    ~Cinta()
    {
    }

    bool tieneElementos()
    {
        return this->contarElementos() > 0;
    }

    bool depositar( const ElementoProduccion& e )
    {
        bool depositoOk = this->getPrimerSlot()->estaVacio();

        if ( depositoOk )
        {
            this->getPrimerSlot()->depositarElemento( e );
        }

        return depositoOk;
    }

    bool avanzar()
    {
        bool avanzoOk;

        if ( this->getUltimoSlot()->estaVacio() )
        {
            m_primerPosicion =
                    ( m_primerPosicion + CANTIDAD_SLOTS - 1 ) % CANTIDAD_SLOTS;
            avanzoOk = true;
        }
        else
        {
            avanzoOk = false;
        }

        return avanzoOk;
    }

    ElementoProduccion quitar()
    {
        ElementoProduccion elem;

        elem = this->getUltimoSlot()->quitarElemento();

        return elem;
    }

    int contarElementos()
    {
        int nElementos = 0;

        for ( int i = 0; i < CANTIDAD_SLOTS; i++ )
        {
            if ( !m_slots[ i ].estaVacio() )
            {
                nElementos++;
            }
        }

        return nElementos;
    }
};

#endif /* CINTA_H_ */
